<?php

namespace app\controller;

use app\AuthController;
use think\facade\Request;
use think\facade\Db;
use think\facade\View;
use think\facade\Session;
use think\facade\Cookie;
use think\captcha\facade\Captcha;
use Hashids\Hashids;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;

use app\model\{
  User as UserModel,
};
use app\BaseInfoController as BaseInfo;

class Login extends AuthController
{


  ###################################################### 【注册用户】 退出登录 、 重新登录 、 切换账号 ##############################################################
  # 退出登录
  public function logout()
  {
    Session::delete('user');
    Cookie::delete('domain-user-info');
    $this->success('退出登录成功', '/', '', 1);
  }

  #############################################################################################################################################################




















  ####################################### 【登录相关4个操作方法】 登录图片验证码 、 发送验证邮件 、 登录页登录功能 、 登录写入Session与Cookie功能 #########################
  # 输出根据登录次数而进行难度变化的登录验证码
  public function verify()
  {
    $frequency = Session::get('login', 0);
    if ($frequency <= 2)
      $captcha = '';
    else if ($frequency <= 4)
      $captcha = 'verify_math';
    else if ($frequency <= 6)
      $captcha = 'verify_en';
    else if ($frequency <= 10)
      $captcha = 'verify_zh';
    else
      $captcha = 'verify_zh';
    return Captcha::create($captcha);
  }

  # 发送邮件登录验证码
  public function send_login_email_captcha()
  {
    if ($this->request->isPost()) {
      #防止短时间内重复发送
      $email_cp_time = Session::get('sendmail.cp_time', 0);
      if ($email_cp_time > 0) {
        if ((time() - $email_cp_time) < 24)
          return json(['state' => 'error', 'info' => '操作频繁，请' . (24 - (time() - $email_cp_time)) . '秒后再试']);
      }
      #获取邮箱信息
      $result = $this->send_email_captcha($this->request->post('email/s'), 'login');
      return json($result);
    }
  }

  # 登录
  public function login()
  {
    #验证不同登录次数展示不同的验证码
    $frequency = Session::get('login', 0);
    # 登录验证功能或登录页面
    if ($this->request->isPost()) {
      $uname = $this->request->post('uname/s');
      $upass = $this->request->post('upass/s');
      $ecapt = $this->request->post('ecapt/s');
      $captc = $this->request->post('captc/s');
      $readm = $this->request->post('readm/d');
      $error['state'] = 'success'; //保存错误信息

      # 验证验证码
      if ($frequency > 2) {
        if (!captcha_check($captc)) {
          return json(['state' => 'error', 'info' => ['验证码不正确']]);
        }
      }

      # 验证邮箱验证码
      $isEmail = '/^([\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/';
      $sendmail = Session::get('sendmail');
      if (($error['state'] == 'success') && (!empty($sendmail))) {
        if (preg_match($isEmail, $uname) || filter_var($uname, FILTER_VALIDATE_EMAIL)) {
          if ($sendmail['email'] != $uname) {
            $error['state']  = 'error';
            $error['info'][] = '您最后输入的邮箱和发送验证码的邮箱不一致';
          }
          if ($ecapt != $sendmail['captcha']) {
            $error['state']  = 'error';
            $error['info'][] = '邮件验证码不正确';
          }
        } else {
          $error['state']  = 'error';
          $error['info'][] = '邮箱格式不正确';
        }
        // 通过验证
        if ($error['state'] == 'success') {
          $userinfo = Db::name('user')->where('email', $sendmail['email'])->findOrEmpty();
          return json($this->html_login($userinfo, $readm, 'Q64')); // 通过验证
        }
      }

      # 验证用户名和密码格式
      if (!preg_match("/^[a-zA-Z\s]+$/", $uname) && !(preg_match($isEmail, $uname) || filter_var($uname, FILTER_VALIDATE_EMAIL))) {
        $error['state']  = 'error';
        $error['info'][] = '用户名 / 邮箱格式不正确';
        return json($error);
      }
      if (!preg_match('/^[0-9_a-zA-Z]{2,16}$/i', $upass)) {
        $error['state']  = 'error';
        $error['info'][] = '密码格式不正确';
        return json($error);
      }
      $userinfo = UserModel::where('account|email', $uname)->find();
      if (empty($userinfo)) {
        $error['state'] = 'error';
        $error['info'][] = '用户名 / 邮箱不存在';
      } else { // 通过验证
        if (!password_verify($upass, $userinfo['pwd'])) {
          $error['state'] = 'error';
          $error['info'][] = '密码错误';
        } else {
          return json($this->html_login($userinfo, $readm, 'wB2')); // 通过验证
        }
      }

      # 输出错误信息并刷新页面
      Session::set('login', ++$frequency);
      if ($frequency == 3) {
        $error['state'] = 'refresh';
        return json($error);
      } else {
        return json($error);
      }
    } else {
      View::assign([
        'site_info' => BaseInfo::siteInfo(),  // 网站信息
        'frequency' => $frequency,            // 验证错误次数
      ]);
      return View::fetch();
    }
  }

  # 通过验证之后进行录入Session与Cookie操作
  protected function html_login($userinfo, $readm, $type)
  {
    # 登录信息录入数据库并更新近期登录时间
    $get_request = $this->request->requestInfo;
    UserModel::where('id', $userinfo['id'])->update(['last_ip' => $get_request['ip'], 'last_time' => $get_request['time']]);
    # 删除登录Session并写入用户Session
    Session::delete('sendmail');
    Session::delete('login');
    $userinfo['last_ip']   = $get_request['ip'];
    $userinfo['last_time'] = $get_request['time'];
    Session::set('user', $userinfo->toArray());
    # 写入Cookie用于自动登录
    if ($readm) {
      $uid = $userinfo['uid'];
      $ups = md5($userinfo['pwd'] . 'choaloveyou');
      $uky = md5($get_request['user_agent'] . 'choaloveyou');
      $ckuser = unserialize(Cookie::get('user'));
      $ckuser['main'] = $uid;
      $ckuser[$uid]   = [$ups, $uky];
      Cookie::forever('user', serialize($ckuser));
    }
    return ['state' => 'success', 'info' => '居然登录成功了，好不容易啊~~'];
  }
  #############################################################################################################################################################




















  ############################################# 【注册相关4个操作方法】 注册页注册功能 、 验证用户名 、 验证用户昵称 、 发送验证邮件 #####################################
  # 前端检测用户名是否合法
  public function checkName()
  {
    if ($this->request->isPost()) {
      $username = $this->request->post('uname/s');
      if (!preg_match("/^[a-zA-Z\s]+$/", $username))
        return json(['state' => 'error', 'info' => '您输入的用户名不符合格式，用户名只能为大小写字母']);
      $isHas = UserModel::where('account', $username)->count();
      if (!$isHas)
        return json(['state' => 'success', 'info' => '恭喜你输入的用户名可以使用']);
      else
        return json(['state' => 'error', 'info' => '用户名已存在，请重新输入']);
    }
  }

  # 前端检测昵称是否合法
  public function checkNick()
  {
    if ($this->request->isPost()) {
      $nick = $this->request->post('unick/s');
      if (!preg_match("/^[\x7f-\xff]+$/", $nick))
        return json(['state' => 'error', 'info' => '您输入的昵称不符合格式，昵称只能为汉字']);
      $isHas = UserModel::where('nick', $nick)->count();
      if (!$isHas)
        return json(['state' => 'success', 'info' => '恭喜你输入的昵称可以使用']);
      else
        return json(['state' => 'error', 'info' => '昵称已存在，请重新输入']);
    }
  }

  # 发送邮件注册验证码
  public function send_register_email_captcha()
  {
    if ($this->request->isPost()) {
      #防止短时间内重复发送
      $email_cp_time = Session::get('sendmail.cp_time', 0);
      if ($email_cp_time > 0) {
        if ((time() - $email_cp_time) < 24)
          return json(['state' => 'error', 'info' => '操作频繁，请' . (24 - (time() - $email_cp_time)) . '秒后再试']);
      }
      #获取邮箱信息
      $result = $this->send_email_captcha($this->request->post('email/s'), 'register');
      return json($result);
    }
  }

  # 注册页面及注册功能
  public function register()
  {
    # 验证不同登录次数展示不同的验证码
    $frequency = Session::get('register', 0);
    if ($frequency <= 2)
      $captcha = 0;
    else if ($frequency <= 6)
      $captcha = 1;
    else
      $captcha = 2;
    # 注册验证功能或注册页面
    if ($this->request->isPost()) {
      // return json(['state'=>'success','info'=>'哇，注册成功，太开心啦~']);
      $uname = $this->request->post('uname/s');
      $unick = $this->request->post('unick/s');
      $upass = $this->request->post('upass/s');
      $ename = $this->request->post('ename/s');
      $ecapt = $this->request->post('ecapt/s');
      $captc = $this->request->post('captc/s');

      $error['state'] = 'success'; //保存错误信息
      #验证验证码
      if ($captcha != 0) {
        if (!captcha_check($captc)) {
          $error['state'] = 'error';
          $error['info'][] = '验证码不正确';
        }
      }
      if ($error['state'] == 'success') {
        if (!preg_match("/^[a-zA-Z\s]+$/", $uname)) {
          $error['state'] = 'error';
          $error['info'][]  = '用户名格式不正确。';
        }
        if (!preg_match('/^[\x{4e00}-\x{9fa5}A-Za-z0-9]+$/u', $unick)) {
          $error['state'] = 'error';
          $error['info'][]  = '昵称格式不正确';
        }
        if (!preg_match('/^[0-9_a-zA-Z]{2,16}$/i', $upass)) {
          $error['state'] = 'error';
          $error['info'][] = '密码格式不正确。';
        }
      }
      if ($error['state'] == 'success') {
        $users = UserModel::where('account', $uname)->count();
        if (!empty($users)) {
          $error['state'] = 'error';
          $error['info'][]  = '用户名已存在';
        }
      }
      $sendmail = Session::get('sendmail');
      if (($error['state'] == 'success') && (!empty($sendmail))) {
        if ($sendmail['email'] != $ename) {
          $error['state']  = 'error';
          $error['info'][] = '您最后输入的邮箱和发送验证码的邮箱不一致';
        }
        $check_email = UserModel::where('email', $sendmail['email'])->count();
        if ($check_email) {
          $error['state']  = 'error';
          $error['info'][] = '邮箱已存在，不能重复注册';
        }
        if ($ecapt != $sendmail['captcha']) {
          $error['state']  = 'error';
          $error['info'][] = '邮件验证码不正确';
        }
      }
      # 注册信息写入数据表
      if ($error['state'] == 'success') {
        $data = [
          'uid' => 'ok',
          'account' => $uname,
          'email' => $ename,
          'pwd' => password_hash($upass, PASSWORD_BCRYPT),
          'nick' => $unick,
          'default_editor' => 'mavoneditor',
          'add_time' => time(),
          'roles' => 10,
        ];
        $result = UserModel::create($data);
        $Hashids = new Hashids('choaloveyou', 5);
        $uid = $Hashids->encode($result->id);
        UserModel::where('id', $result->id)->update(['uid' => $uid, 'master_id' => $result->id]);
        Session::delete('sendmail');
        Session::set('register', ++$frequency);
        return json(['state' => 'success', 'info' => '哇，注册成功，太开心啦~']);
      } else {
        return json($error);
      }
    } else {
      View::assign([
        'site_info' => BaseInfo::siteInfo(),  // 网站信息
        'captcha'   => $captcha,              // 验证码
      ]);
      return View::fetch();
    }
  }
  #############################################################################################################################################################




















  ##########################################################发送邮件验证码 、 发送邮件基础功能######################################################################
  /**
   * 发送邮件验证码
   * 邮件里的网站名称是写死的
   * @param  注册验证码 register
   * @param  登录验证码 login
   * @param  更换验证码
   */
  protected function send_email_captcha($email, $operation)
  {
    # 验证邮箱格式
    $isEmail = '/^([\.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/';
    if (!preg_match($isEmail, $email) && !filter_var($email, FILTER_VALIDATE_EMAIL))
      return ['state' => 'error', 'info' => '邮箱格式不正确'];
    # 生成4位随机数验证码
    $arr = array_merge(range('0', '9'));
    shuffle($arr);
    $arr = array_flip($arr);
    $arr = array_rand($arr, 4);
    $captcha = '';
    foreach ($arr as $v)
      $captcha .= $v;
    # 根据不同类型验证码生成不同发送内容
    switch ($operation) {
      case 'register': // 注册操作
        $check_email = UserModel::where('email', $email)->count();
        // return ['state'=>'error','info'=>$check_email];
        if ($check_email) return ['state' => 'error', 'info' => '邮箱已存在，不能重复注册'];
        $subject = '注册账号 - 梦幻空间站';
        View::assign([
          'captcha'   => $captcha,
          'operation' => '注册账号',
        ]);
        $body = View::fetch('email_html_captcha_2');
        $altbody = '您的验证码是：' . $captcha . '，如果您未进行注册账号操作，请忽略该邮件。--【梦幻空间站 - 个人博客 - www.soyul.cn】';
        $dt[1] = 'QM8';
        $dt[2] = '';
        break;
      case 'login': // 登录操作
        $check_email = UserModel::where('email', $email)->count();
        if ($check_email) return ['state' => 'error', 'info' => '邮箱不存在'];
        $subject = '账号登录 - 梦幻空间站';
        View::assign([
          'captcha'   => $captcha,
          'operation' => '登录',
          'subject'   => $subject,
          'username'  => $check_email['nick'],
        ]);
        $body = View::fetch('email_html_captcha_1');
        $altbody = '您的验证码是：' . $captcha . '，如果您未进行登录操作，请忽略该邮件。--【梦幻空间站 - 个人博客 - www.soyul.cn】';
        $dt[1] = 'Q4W';
        $dt[2] = $check_email['uid'];
        break;
      default:
        return ['state' => 'error', 'info' => '空操作'];
    }
    #发送验证码
    $result = $this->send_email($email, $subject, $body, $altbody);
    # 网站请求信息记录
    $get_request = $this->request->requestInfo;
    $get_request['request_code'] = $dt[1];
    $get_request['user_id']   = $dt[2];
    $get_request['info2'] = $email;
    $get_request['info3'] = $subject;
    $get_request['info4'] = $body;
    $get_request['info5'] = $altbody;
    if ($result['state'] == 'success') {
      // $get_request['info1'] = 1;
      // Db::name('website_request')->insert($get_request);
      // 邮箱 、 验证码 、 发送时间写入Session
      $sendmail['email']   = $email;
      $sendmail['captcha'] = $captcha;
      $sendmail['cp_time'] = time();
      Session::set('sendmail', $sendmail);

      return ['state' => 'success', 'info' => $result['content']];
    } else {
      // $get_request['info1'] = 0;
      // Db::name('website_request')->insert($get_request);

      return ['state' => 'error', 'info' => $result['content']];
    }
  }

  /**
   * 发送邮件基础功能
   * 邮件里的网站名称是写死的
   * @param  $email    邮箱
   * @param  $subject  标题
   * @param  $body     主要内容
   * @param  $altbody  备用内容
   */
  protected function send_email($email, $subject, $body, $altbody)
  {
    $mail = new PHPMailer(true);
    try {
      // $mail->SMTPDebug = 1;
      $mail->isSMTP();
      $mail->Host       = 'smtp.qq.com';
      $mail->SMTPAuth   = true;
      $mail->Username   = 'choasmida@foxmail.com';
      $mail->Password   = 'gtehplhocbyzbdbc';
      $mail->SMTPSecure = 'ssl';
      $mail->Port       = 465;
      $mail->CharSet    = 'UTF-8';
      $mail->setFrom('choasmida@foxmail.com', '【梦幻空间站-个人博客】');
      $mail->isHTML(true);

      $mail->addAddress($email);
      $mail->Subject = $subject;
      $mail->Body    = $body;
      $mail->AltBody = $altbody;

      $mail->send();
      $result = ['state' => 'success', 'content' => '邮件发送成功'];
    } catch (Exception $e) {
      $result = ['state' => 'error', 'content' => '邮件发送失败：' . $mail->ErrorInfo];
    }
    return $result;
  }
}
